/*-
 * #%L
 * Spring Auto REST Docs Core
 * %%
 * Copyright (C) 2015 - 2018 Scalable Capital GmbH
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */
package com.runfast.common.restdoc.snippet;

import capital.scalable.restdocs.OperationAttributeHelper;
import capital.scalable.restdocs.SnippetRegistry;
import capital.scalable.restdocs.section.SectionSupport;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.IOFileFilter;
import org.apache.commons.io.filefilter.TrueFileFilter;
import org.slf4j.Logger;
import org.springframework.restdocs.RestDocumentationContext;
import org.springframework.restdocs.operation.Operation;
import org.springframework.restdocs.snippet.RestDocumentationContextPlaceholderResolverFactory;
import org.springframework.restdocs.snippet.Snippet;
import org.springframework.restdocs.snippet.TemplatedSnippet;
import org.springframework.restdocs.snippet.WriterResolver;
import org.springframework.util.PropertyPlaceholderHelper;
import org.springframework.web.method.HandlerMethod;

import java.io.File;
import java.util.*;

import static capital.scalable.restdocs.OperationAttributeHelper.*;
import static capital.scalable.restdocs.i18n.SnippetTranslationResolver.translate;
import static org.apache.commons.lang3.StringUtils.*;
import static org.slf4j.LoggerFactory.getLogger;
import static org.springframework.util.StringUtils.capitalize;

public class ClassSectionSnippet extends TemplatedSnippet {
    private static final Logger log = getLogger(ClassSectionSnippet.class);

    public static final String SECTION = "auto-class-section";

    public static final String ITEM_SECTION = "auto-section";


    private final RestDocumentationContextPlaceholderResolverFactory placeholderResolverFactory =
            new RestDocumentationContextPlaceholderResolverFactory();

    private final PropertyPlaceholderHelper propertyPlaceholderHelper =
            new PropertyPlaceholderHelper("{", "}");


    public ClassSectionSnippet() {
        super(SECTION, null);
    }

    @Override
    protected Map<String, Object> createModel(Operation operation) {
        Map<String, Object> model = defaultModel(operation);

        HandlerMethod handlerMethod = getHandlerMethod(operation);

        DefaultJavadocReader javadocReader = (DefaultJavadocReader) getJavadocReader(operation);
        if (handlerMethod != null) {
            String title = resolveTitle(handlerMethod, javadocReader);

            model.put("title", title);
        }

        return model;
    }

    private List<Section> createSections(Operation operation) {
        List<Section> sections = new ArrayList<>();
        new Section("", "");
        return sections;
    }

    private Map<String, Object> defaultModel(Operation operation) {
        // resolve path
        String classOutPath = propertyPlaceholderHelper.replacePlaceholders(operation.getName(),
                placeholderResolverFactory.create(getDocumentationContext(operation)));


        Map<String, Object> model = new HashMap<>();
        model.put("title", createTitle(operation.getName()));
        model.put("link", delimit(classOutPath));
        model.put("classPath", classOutPath);

        List<Section> sections = new ArrayList<>();

        RestDocumentationContext context = (RestDocumentationContext) operation
                .getAttributes().get(RestDocumentationContext.class.getName());
        WriterResolver writerResolver = (WriterResolver) operation.getAttributes()
                .get(WriterResolver.class.getName());

        PropertyPlaceholderHelper.PlaceholderResolver placeholderResolver = this.placeholderResolverFactory
                .create(context);
        final String sectionFileName = propertyPlaceholderHelper.replacePlaceholders(ITEM_SECTION, placeholderResolver) + "."
                + OperationAttributeHelper.getTemplateFormat(operation).getFileExtension();

        File classOutputDir = new File(classOutPath);
        if (!classOutputDir.isAbsolute()) {
            File configuredOutputDir = context.getOutputDirectory();
            if (configuredOutputDir != null) {
                classOutputDir = new File(configuredOutputDir, classOutputDir.getPath());
            }
        }

        if (classOutputDir != null) {
            Iterator<File> fileIterator = FileUtils.iterateFiles(classOutputDir, new IOFileFilter() {
                @Override
                public boolean accept(File file) {
                    return file.getName().equals(sectionFileName);
                }

                @Override
                public boolean accept(File dir, String name) {
                    return true;
                }
            }, TrueFileFilter.INSTANCE);

            while (fileIterator.hasNext()) {
                File file = fileIterator.next();
                Section section = new Section(file.getParentFile().getName(), "");
                sections.add(section);

            }
        }


        model.put("sections", sections);


        return model;
    }

    private String resolveTitle(HandlerMethod handlerMethod, DefaultJavadocReader javadocReader) {
        String title = javadocReader.resolveClassComment(handlerMethod.getBeanType());
        if (isBlank(title)) {
            title = createTitle(handlerMethod.getBeanType().getSimpleName());
        }
        boolean isDeprecated = handlerMethod.getMethod().getAnnotation(Deprecated.class) != null;
        if (isDeprecated) {
            return translate("tags-deprecated-title", title);
        } else {
            return title;
        }
    }

    private String createTitle(String name) {
        return join(splitByCharacterTypeCamelCase(capitalize(name)), ' ');
    }

    private SectionSupport getSectionSnippet(Operation operation, String snippetName) {
        for (Snippet snippet : getDefaultSnippets(operation)) {
            if (snippet instanceof SectionSupport) {
                SectionSupport sectionSnippet = (SectionSupport) snippet;
                if (snippetName.equals(sectionSnippet.getFileName())) {
                    return sectionSnippet;
                }
            }
        }

        return SnippetRegistry.getClassicSnippet(snippetName);
    }

    private String delimit(String value) {
        return value.replace("/", "-");
    }

    static class Section {
        String fileName;
        String header;

        public Section(String fileName, String header) {
            this.fileName = fileName;
            this.header = header;
        }
    }
}
